package cn.wolfcode.rbac.service.impl;

import cn.wolfcode.rbac.domain.Permission;
import cn.wolfcode.rbac.mapper.PermissionMapper;
import cn.wolfcode.rbac.qo.QueryObject;
import cn.wolfcode.rbac.service.IPermissionService;
import cn.wolfcode.rbac.web.annotation.RequiredPermission;
import cn.wolfcode.rbac.web.exception.BusinessException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.*;

import static cn.wolfcode.rbac.common.RedisKeyPrefix.CACHE_PREFIX;

/**
 * 权限业务
 */
@Service
@Transactional
public class PermissionServiceImpl implements IPermissionService {

    /**
     * 权限加载
     * 方式1：通过ApplicationContext 即Spring的容器对象获取Controller再获取对应的方法以及注解
     * 方式2：通过SpringMVC的RequestHandlerMapping对象获取Controller再获取对应的方法以及注解
     */

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Autowired
    private PermissionMapper permissionMapper;


    @Override
    public void load() {
        //0.查询所有权限
        List<String> list = permissionMapper.selectExpression();

        // 方式1：spring的applicationContext容器对象
        //1.通过ApplicationContext容器对象获取所有的贴有@Controller注解的bean
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Controller.class);
        Collection<Object> values = beans.values();
        //2.获取Controller对象中的method,但不包括父类的方法
        values.forEach(controller -> {
            Method[] methods = controller.getClass().getDeclaredMethods();
            //3.通过方法对象获取@RequiredPermission注解
            Arrays.stream(methods).forEach(item -> {
                //4.获取每个个注解
                RequiredPermission annotation = item.getAnnotation(RequiredPermission.class);
                if (annotation == null) {
                    return;
                }
                //5.获取注解中的属性
                String name = annotation.name();
                String expression = annotation.expression();
                // 如果没有权限，则加载
                if (!list.contains(expression)) {
                    //6.将属性注入Permission对象
                    Permission permission = new Permission(name, expression);
                    //7.调用PermissionMapper对象存入数据库
                    // 注意：存入数据库前，先检查数据库中是否已经有该权限
                    permissionMapper.insert(permission);
                }
            });
        });


        /*
        方式2：通过SpringMVC中的RequestMappingHandlerMapping请求对象
        Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
        Collection<HandlerMethod> handlerMethods = map.values();
        handlerMethods.forEach(handlerMethod -> {
            //写法1
            RequiredPermission annotation = handlerMethod.getMethodAnnotation(RequiredPermission.class);
            //写法2
//            RequiredPermission annotation = handlerMethod.getMethod().getAnnotation(RequiredPermission.class);
            if (annotation == null) {
                return;
            }
            //5.获取注解中的属性
            String name = annotation.name();
            String expression = annotation.expression();
            // 如果没有权限，则加载
            if (!list.contains(expression)) {
                //6.将属性注入Permission对象
                Permission permission = new Permission(name, expression);
                //7.调用PermissionMapper对象存入数据库
                // 注意：存入数据库前，先检查数据库中是否已经有该权限
                permissionMapper.insert(permission);
            }
        });*/

    }

    @Override
    public PageInfo<Permission> list(QueryObject qo) {
        PageHelper.startPage(qo.getPageNum(),qo.getPageSize());
        List<Permission> permissions = permissionMapper.selectAll();
        return new PageInfo(permissions);
    }

    @Override
    public List<Permission> queryPermission(Long id) {
        List<Permission> permissions = permissionMapper.selectPermissionsByRoleId(id);
        return permissions;
    }

}
